import 'dart:convert';
import 'dart:math' as math;

import 'package:deepseek_desktop/components/ModelController.dart';
import 'package:deepseek_desktop/components/chat/ChatSettingController.dart';
import 'package:deepseek_desktop/controller/SettingController.dart';
import 'package:deepseek_desktop/entity/Model.dart';
import 'package:deepseek_desktop/utils/Util.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:file_picker/file_picker.dart';

class ChatInput extends StatelessWidget {
  final InputFinish onFinish;
  ChatInput({super.key, required this.onFinish});

  final TextEditingController controller = TextEditingController();
  final FocusNode focusNode = FocusNode();
  final FocusNode focusNode2 = FocusNode();

  final ChatSettingController chatSettingController =
      Get.put(ChatSettingController());

  final ModelController modelController = Get.put(ModelController());
  final RxString selectedImage = ''.obs;

  final SettingController settingController = Get.put(SettingController());

  final ScrollController _scrollController = ScrollController();
  final _attachmentHoverStates = <PlatformFile, RxBool>{};
  final RxDouble _inputHeight = 220.0.obs;
  final RxBool _isDragging = false.obs;
  final RxBool _isSending = false.obs;
  final RxBool _showStopButton = false.obs;
  final RxBool _isGrayColor = true.obs;
  final RxBool _isBeforeRenderCancel = false.obs;
  final RxBool _isAfterRenderCancel = false.obs;
  @override
  Widget build(BuildContext context) {
    return Obx(
      () => Container(
        color: const Color.fromARGB(255, 252, 252, 252),
        height: _inputHeight.value,
        child: Column(
          children: [
            // 新增附件信息显示区域
            Obx(() => chatSettingController
                    .currentChat.value.selectedAttachments.isNotEmpty
                ? Container(
                    height: 45,
                    padding: const EdgeInsets.only(top: 15, left: 5, bottom: 5),
                    width: double.infinity,
                    decoration: const BoxDecoration(),
                    clipBehavior: Clip.hardEdge,
                    child: Listener(
                      onPointerSignal: (pointerSignal) {
                        // 处理鼠标滚轮事件
                        if (pointerSignal is PointerScrollEvent) {
                          // 获取滚轮滚动量
                          final scrollDelta = pointerSignal.scrollDelta;
                          // 水平滚动处理
                          if (scrollDelta.dx != 0) {
                            _scrollController.jumpTo(
                                _scrollController.offset + scrollDelta.dx);
                          }
                          // 垂直滚轮转换为水平滚动
                          else if (scrollDelta.dy != 0) {
                            double newOffset =
                                _scrollController.offset + scrollDelta.dy;
                            newOffset = newOffset.clamp(0.0,
                                _scrollController.position.maxScrollExtent);
                            _scrollController.jumpTo(newOffset);
                          }
                        }
                      },
                      onPointerMove: (PointerMoveEvent event) {
                        // 新增触摸板手势
                        if (event.delta.dx != 0) {
                          double newOffset =
                              _scrollController.offset - event.delta.dx;
                          newOffset = newOffset.clamp(
                              0.0, _scrollController.position.maxScrollExtent);
                          _scrollController.jumpTo(newOffset);
                        }
                      },
                      child: ListView.builder(
                        clipBehavior: Clip.none,
                        controller: _scrollController, // 使用明确的滚动控制器
                        scrollDirection: Axis.horizontal,
                        physics: const ClampingScrollPhysics(
                            parent: AlwaysScrollableScrollPhysics()),
                        itemCount: chatSettingController
                            .currentChat.value.selectedAttachments.length,
                        itemBuilder: (context, index) {
                          final file = chatSettingController
                              .currentChat.value.selectedAttachments[index];
                          // 初始化悬停状态
                          _attachmentHoverStates[file] ??= false.obs;
                          final isHovering = _attachmentHoverStates[file]!;
                          return MouseRegion(
                            onEnter: (_) => isHovering.value = true,
                            onExit: (_) => isHovering.value = false,
                            child: Stack(
                              clipBehavior: Clip.none,
                              children: [
                                Container(
                                  margin: const EdgeInsets.only(right: 10),
                                  padding: const EdgeInsets.symmetric(
                                      horizontal: 8, vertical: 4),
                                  decoration: BoxDecoration(
                                    color: Colors.grey[200],
                                    borderRadius: BorderRadius.circular(12),
                                  ),
                                  child: Row(
                                    children: [
                                      const Icon(Icons.insert_drive_file,
                                          size: 16),
                                      const SizedBox(width: 4),
                                      Text(
                                        file.name,
                                        style: const TextStyle(fontSize: 12),
                                      ),
                                      const SizedBox(width: 4),
                                      Text(
                                        '(${_formatFileSize(file.size)})',
                                        style: TextStyle(
                                          fontSize: 12,
                                          color: Colors.grey[600],
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                                Obx(() => isHovering.value
                                    ? Positioned(
                                        top: -6,
                                        right: 0,
                                        child: Container(
                                          decoration: BoxDecoration(
                                            shape: BoxShape.circle,
                                            boxShadow: [
                                              BoxShadow(
                                                color: Colors.black
                                                    .withOpacity(0.05),
                                                blurRadius: 3,
                                                spreadRadius: 1,
                                              )
                                            ],
                                          ),
                                          child: IconButton(
                                            padding: EdgeInsets.zero,
                                            constraints: const BoxConstraints(
                                              minWidth: 22,
                                              minHeight: 22,
                                            ),
                                            iconSize: 14,
                                            icon: Container(
                                              decoration: const BoxDecoration(
                                                color: Colors.grey,
                                                shape: BoxShape.circle,
                                              ),
                                              padding: const EdgeInsets.all(3),
                                              child: const Icon(
                                                Icons.close,
                                                color: Colors.white,
                                                size: 10,
                                              ),
                                            ),
                                            onPressed: () {
                                              chatSettingController.currentChat
                                                  .update((val) {
                                                val!.selectedAttachments
                                                    .remove(file);

                                                Util.writeFile(
                                                    'chats/${chatSettingController.currentChat.value.id}.json',
                                                    jsonEncode(
                                                        chatSettingController
                                                            .currentChat
                                                            .value));
                                              });

                                              _attachmentHoverStates
                                                  .remove(file);
                                            },
                                          ),
                                        ),
                                      )
                                    : const SizedBox.shrink()),
                              ],
                            ),
                          );
                        },
                      ),
                    ))
                : const SizedBox.shrink()),
            GestureDetector(
                behavior: HitTestBehavior.opaque,
                onVerticalDragStart: (_) => _isDragging.value = true,
                onVerticalDragEnd: (_) => _isDragging.value = false,
                onVerticalDragUpdate: (details) {
                  final newHeight = _inputHeight.value - details.delta.dy;
                  _inputHeight.value = newHeight.clamp(220.0, 500.0);
                },
                child: MouseRegion(
                    cursor: SystemMouseCursors.resizeUpDown,
                    child: Obx(
                      () => Column(
                        children: [
                          Container(
                            height: 10,
                            alignment: Alignment.center,
                            child: Container(
                              width: 40,
                              height: 4,
                              margin: const EdgeInsets.only(bottom: 3),
                              decoration: BoxDecoration(
                                color: _isDragging.value
                                    ? Colors.blue[400]
                                    : Colors.grey[400],
                                borderRadius: BorderRadius.circular(2),
                              ),
                            ),
                          ),
                          Divider(
                            height: 1,
                            color: Colors.grey.withOpacity(0.2),
                          ),
                        ],
                      ),
                    ))),
            Row(
              children: [
                IconButton(
                    onPressed: () async {
                      // 选择多个文件，限制最多50个，支持图片和文档
                      FilePickerResult? result =
                          await FilePicker.platform.pickFiles(
                        allowMultiple: true,
                        type: FileType.custom,
                        allowedExtensions: [
                          'jpg',
                          'jpeg',
                          'png',
                          'bmp',
                          'gif',
                          'pdf',
                          'doc',
                          'docx',
                          'txt',
                          'xls',
                          'xlsx',
                          'ppt',
                          'pptx'
                        ],
                        withData: true,
                      );

                      if (result == null) return; // 用户取消选择

                      if (result.files.length > 50) {
                        // 超过数量限制
                        _showSnackBar("最多只能选择50个文件");
                        return;
                      }

                      for (var file in result.files) {
                        if (file.size > 100 * 1024 * 1024) {
                          // 超过大小限制
                          _showSnackBar('文件 ${file.name} 超过100MB大小限制，无法上传');
                          return;
                        }
                      }

                      // 依次上传文件并识别文字，拼接结果
                      StringBuffer recognizedTexts = StringBuffer();
                      await Future.forEach(result.files, (file) async {
                        try {
                          String content = await Util.extractFileContent(file);

                          if (content.isNotEmpty) {
                            if (content.startsWith('不支持的文件类型')) {
                              _showSnackBar('文件 ${file.name} 不支持的文件类型');
                              return Future.error('文件 ${file.name} 不支持的文件类型');
                            }
                            if (content.startsWith('OCR处理失败')) {
                              _showSnackBar('文件 ${file.name} $content');
                              return Future.error('文件 ${file.name} $content');
                            }
                            if (content.startsWith('DOCX解析异常')) {
                              _showSnackBar(
                                  '文件 ${file.name} DOCX解析异常: $content');
                              return Future.error(
                                  '文件 ${file.name} DOCX解析异常: $content');
                            }
                            recognizedTexts.writeln('文件 ${file.name} 内容：');
                            recognizedTexts.writeln(content);
                            recognizedTexts.writeln('\n---\n');
                          }
                        } catch (e) {
                          _showSnackBar(
                              '文件 ${file.name} 解析失败: ${e.toString()}');
                          return Future.error(
                              '文件 ${file.name} 解析失败: ${e.toString()}');
                        }
                      }).then((_) async {
                        if (recognizedTexts.isNotEmpty && onFinish != null) {
                          // 添加附件信息到响应式变量
                          chatSettingController
                              .currentChat.value.selectedAttachments
                              .addAll(result.files);

                          onFinish(
                            recognizedTexts.toString(),
                            modelController.selectModel.value.name,
                            showChat: false,
                            showStopButton: _showStopButton,
                            isSending: _isSending,
                            isGrayColor: _isGrayColor,
                            isBeforeRenderCancel: _isBeforeRenderCancel,
                            isAfterRenderCancel: _isAfterRenderCancel,
                          );
                        }
                      }).catchError((error) {
                        debugPrint('识别错误：$error');
                      });
                    },
                    icon: const Icon(Icons.attach_file),
                    tooltip: '上传附件（仅识别文字）\n最多 50 个，每个 100 MB，支持各类文档和图片'),
                Expanded(child: Container()),
                Obx(() => DropdownButton<Model>(
                      value: modelController.selectModel.value,
                      items: modelController.items.map((Model value) {
                        return DropdownMenuItem<Model>(
                          value: value,
                          child: Text(value.displayName),
                        );
                      }).toList(),
                      underline: Container(),
                      onChanged: (newValue) {
                        modelController.selectModel.value = newValue!;
                        modelController.update();
                      },
                    )),

                // IconButton(onPressed: (){}, icon: Row(
                //   children: [
                //     Icon(Icons.model_training),
                //     const SizedBox(width: 5,),
                //     Text('gpt-3.5-turbo')
                //   ],
                // )),
              ],
            ),
            Expanded(
                child: Stack(children: [
              RawKeyboardListener(
                focusNode: focusNode,
                onKey: handleKeyPress,
                child: TextField(
                  cursorColor: Colors.black.withAlpha(255),
                  cursorWidth: 1,
                  cursorHeight: 22,
                  decoration: const InputDecoration(
                    hintText: '写点什么吧，按Enter发送消息，Shift+Enter换行',
                    border: OutlineInputBorder(
                      borderSide: BorderSide.none,
                    ),
                  ),
                  style: const TextStyle(
                    fontSize: 12,
                  ),
                  maxLines: null,
                  controller: controller,
                  onChanged: (value) {
                    if (value.isNotEmpty) {
                      _isGrayColor.value = false;
                    } else {
                      _isGrayColor.value = true;
                    }
                  },
                ),
              ),
              Positioned(
                right: 5,
                bottom: 5,
                child: Obx(() => MouseRegion(
                    cursor: (controller.text.isEmpty && !_showStopButton.value)
                        ? SystemMouseCursors.forbidden
                        : SystemMouseCursors.click,
                    child: IgnorePointer(
                        ignoring:
                            controller.text.isEmpty && !_showStopButton.value,
                        child: Container(
                          margin: const EdgeInsets.all(10),
                          child: SizedBox(
                            width: 32,
                            height: 32,
                            child: ElevatedButton(
                              style: ElevatedButton.styleFrom(
                                padding: EdgeInsets.zero,
                                shape: const CircleBorder(),
                                backgroundColor:
                                    _showStopButton.value && _isSending.value
                                        ? Colors.blue
                                        : Colors.transparent,
                                foregroundColor: controller.text.isEmpty &&
                                        _isGrayColor.value
                                    ? Colors.grey
                                    : Colors.blue,
                                shadowColor: Colors.transparent,
                                elevation: 0,
                                tapTargetSize: MaterialTapTargetSize.shrinkWrap,
                                alignment: Alignment.center,
                              ),
                              child: _isSending.value
                                  ? _showStopButton.value
                                      ? const Icon(Icons.stop,
                                          color: Colors.white, size: 22)
                                      : const SizedBox(
                                          width: 16,
                                          height: 16,
                                          child: CircularProgressIndicator(
                                              color: Colors.blue,
                                              strokeWidth: 2),
                                        )
                                  : Transform.rotate(
                                      angle: -math.pi / 2, // 逆时针旋转90度
                                      child: const Icon(Icons.send, size: 24)),
                              onPressed: () {
                                if (_isSending.value) {
                                  // 如果正在发送，点击停止按钮
                                  if (_showStopButton.value) {
                                    _isSending.value = false;
                                    _showStopButton.value = false;
                                    _isGrayColor.value = true;
                                    _isBeforeRenderCancel.value = true;
                                  }
                                  return;
                                }
                                if (controller.text.trim().isEmpty &&
                                    !_showStopButton.value) {
                                  return;
                                }

                                // 如果有内容但没有发送，则发送
                                // 如果没有内容但显示停止按钮（表示中断状态），则继续生成
                                if (controller.text.trim().isNotEmpty) {
                                  handleSubmit();
                                } else if (_showStopButton.value) {
                                  // 继续生成的逻辑可以在这里添加
                                  // 当前实现是停止后需要重新发送消息
                                }
                              },
                            ),
                          ),
                        )))),
              ),
            ]))
          ],
        ),
      ),
    );
  }

  void _showSnackBar(String message) {
    // 关闭当前可能存在的 snackbar
    if (Get.isSnackbarOpen) Get.closeAllSnackbars();
    Get.snackbar('错误提示', message,
        snackPosition: SnackPosition.BOTTOM,
        duration: const Duration(seconds: 3),
        backgroundColor: Colors.redAccent,
        colorText: Colors.white,
        borderRadius: 8.0,
        margin: const EdgeInsets.all(16.0),
        padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 12.0),
        animationDuration: const Duration(milliseconds: 300),
        forwardAnimationCurve: Curves.easeOutBack,
        reverseAnimationCurve: Curves.easeInCirc,
        boxShadows: [
          BoxShadow(
            color: Colors.red.withOpacity(0.2),
            spreadRadius: 2,
            blurRadius: 8,
            offset: const Offset(0, 4),
          )
        ],
        isDismissible: true,
        dismissDirection: DismissDirection.horizontal,
        icon: const Icon(Icons.info_outline, color: Colors.white),
        shouldIconPulse: false);
  }

  handleSubmit() {
    String text = controller.text;
    controller.clear();
    _isGrayColor.value = true;
    _isSending.value = true;
    onFinish(
      text,
      modelController.selectModel.value.name,
      showStopButton: _showStopButton,
      isSending: _isSending,
      isGrayColor: _isGrayColor,
      isBeforeRenderCancel: _isBeforeRenderCancel,
      isAfterRenderCancel: _isAfterRenderCancel,
    );
  }

  handleKeyPress(event) {
    if (event is RawKeyUpEvent) {
      if (event.logicalKey.keyLabel == "Enter" && !event.isShiftPressed) {
        final val = controller.value;
        final messageWithoutNewLine =
            controller.text.substring(0, val.selection.start - 1) +
                controller.text.substring(val.selection.start);
        controller.value = TextEditingValue(
          text: messageWithoutNewLine,
          selection: TextSelection.fromPosition(
            TextPosition(offset: messageWithoutNewLine.length),
          ),
        );

        handleSubmit();
      }
    }
  }

  String _formatFileSize(int bytes) {
    if (bytes < 1024) return '$bytes B';
    if (bytes < 1048576) return '${(bytes / 1024).toStringAsFixed(1)} KB';
    return '${(bytes / 1048576).toStringAsFixed(1)} MB';
  }
}

typedef InputFinish = void Function(
  String message,
  String model, {
  bool showChat,
  required RxBool showStopButton,
  required RxBool isSending,
  required RxBool isGrayColor,
  required RxBool isBeforeRenderCancel,
  required RxBool isAfterRenderCancel,
});
